﻿using CoreDomain.BusinessCore;
using DomainService.IService.Sys;
using Infrastructure;
using Infrastructure.IRepository.Sys;
using Infrastructure.Repository.Sys;
using Model;
using Model.BusinessModel.OutPut;
using Model.BusinessModel.OutPut.sys;
using System.Reflection;
using Utility;
using Utility.Enum;

namespace DomainService.Service.Sys
{
    /// <summary>
    /// 菜单服务实现
    /// </summary>
    public class SysMenuService : ISysMenuService
    {
        #region 构造实例化

        /// <summary>
        /// 菜单仓储接口
        /// </summary>
        private readonly ISysMenuRepository _menuRepository;

        /// <summary>
        /// 公司仓储接口
        /// </summary>
        private readonly ISysCorporationRepository _sysCorporationRepository;

        /// <summary>
        /// 系统仓储接口
        /// </summary>
        private readonly ISysSystemRepository _sysSystemRepository;

        /// <summary>
        ///  用户底层仓储
        /// </summary>
        private readonly ISysUserRepository _sysUserRepository;


        /// <summary>
        /// 用户角色关系仓储
        /// </summary>
        private readonly ISysUserRoleRelationRepository _sysUserRoleRelationRepository;

        /// <summary>
        /// 菜单角色关系仓储
        /// </summary>
        private readonly ISysMenuRoleRelationRepository _sysMenuRoleRelationRepository;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="menuRepository"></param>
        /// <param name="sysCorporationRepository"></param>
        /// <param name="sysSystemRepository"></param>
        /// <param name="sysMenuRoleRelationRepository"></param>
        /// <param name="sysUserRepository"></param>
        public SysMenuService(ISysMenuRepository menuRepository, ISysCorporationRepository sysCorporationRepository, ISysSystemRepository sysSystemRepository, ISysUserRepository sysUserRepository, ISysUserRoleRelationRepository sysUserRoleRelationRepository, ISysMenuRoleRelationRepository sysMenuRoleRelationRepository)
        {
            _menuRepository = menuRepository;
            _sysCorporationRepository = sysCorporationRepository;
            _sysSystemRepository = sysSystemRepository;
            _sysUserRepository = sysUserRepository;
            _sysUserRoleRelationRepository = sysUserRoleRelationRepository;
            _sysMenuRoleRelationRepository = sysMenuRoleRelationRepository;
        }

        #endregion

        #region 业务逻辑

        /// <summary>
        /// 获取OverallAuth系统树形菜单
        /// </summary>
        /// <returns></returns>
        public List<SysMenuOutPut> GetMenuTreeList()
        {
            var menuList = _menuRepository.GetMenuTreeList();
            List<SysMenuOutPut> list = new();
            //模型的转换
            foreach (var item in menuList)
            {
                SysMenuOutPut model = new()
                {
                    Id = item.Id,
                    Pid = item.Pid,
                    CorporationKey = item.CorporationKey,
                    SystemKey = item.SystemKey,
                    Path = item.Path,
                    Name = item.Name,
                    MenuIcon = item.MenuIcon,
                    Component = item.Component,
                    IsOpen = item.IsOpen,
                    Sort = item.Sort,
                    RequireAuth = item.RequireAuth,
                    Redirect = item.Redirect,
                    CreateTime = item.CreateTime,
                    CreateUser = item.CreateUser,
                };
                list.Add(model);
            }
            var menuTreeList = MenuCore.GetMenuTreeList(list);
            return menuTreeList;
        }

        /// <summary>
        /// 获取用户所属菜单
        /// </summary>
        /// <param name="userId">用户id</param>
        /// <param name="corporationKey">公司key</param>
        /// <param name="systemKey">系统key</param>
        /// <returns>返回用户所属菜单</returns>
        public ReceiveStatus<SysMenuOutPut> GetMenuByUserId(string userId, string corporationKey, string systemKey)
        {
            ReceiveStatus<SysMenuOutPut> receiveStatus = new ReceiveStatus<SysMenuOutPut>();

            //获取用户，并验证
            var userModel = _sysUserRepository.GetByKey(userId, BaseSqlRepository.sysUser_selectByKeySql);
            if (userModel == null)
                return ExceptionHelper<SysMenuOutPut>.CustomExceptionData(string.Format("用户Id【{0}】不存在", userId));
            if (!userModel.IsOpen)
                return ExceptionHelper<SysMenuOutPut>.CustomExceptionData(string.Format("用户【{0}】未启用", userModel.UserName));

            //不是登录星晨公司key的账号，默认赋值一个权限
            var userRoleList = new List<SysUserRoleRelationOutPut>();
            if (corporationKey != Const.XC_CorporationKey)
                userRoleList.Add(new SysUserRoleRelationOutPut { RoleId = Const.XC_DefaultRole });
            else
            {
                //获取用户角色，并验证
                userRoleList = _sysUserRoleRelationRepository.GetSysUserRoleRelationsByUserId(userModel.UserId ?? string.Empty, corporationKey, systemKey).Where(f => f.IsOpen).ToList();
                if ((userRoleList == null || userRoleList.Count == 0))
                    return ExceptionHelper<SysMenuOutPut>.CustomExceptionData(string.Format("用户【{0}】未分配角色,或绑定角色未开启", userModel.UserName));
            }
            var roleIdList = userRoleList.Select(f => f.RoleId).ToList();

            //递归获取角色下，说有角色，并去重  ps:因为我们的角色有继承关系，上级角色会继承下级角色的所有权限
            List<int> roleKeyList = new List<int>();
            foreach (var role in roleIdList)
            {
                var key = RoleCore.GetChildrenRoleById(role, corporationKey, systemKey);
                roleKeyList.AddRange(key);
                roleKeyList.Add(role);
            }
            roleKeyList = roleKeyList.Distinct().ToList();

            //获取角色菜单
            var menuRoleList = _sysMenuRoleRelationRepository.GetSysMenuRoleRelationByRoleId(roleKeyList);
            if (menuRoleList == null || menuRoleList.Count == 0)
                return ExceptionHelper<SysMenuOutPut>.CustomExceptionData(string.Format("用户【{0}】未分配菜单", userModel.UserName));

            //递归菜单并返回
            var menuIdList = menuRoleList.GroupBy(f => f.MenuId).Select(f => f.Key).ToList();
            var menuList = _menuRepository.GetMenusByMenuIdList(menuIdList);
            List<SysMenuOutPut> list = new();

            //模型的转换
            foreach (var item in menuList)
            {
                SysMenuOutPut model = new()
                {
                    Id = item.Id,
                    Pid = item.Pid,
                    CorporationKey = item.CorporationKey,
                    SystemKey = item.SystemKey,
                    Path = item.Path,
                    Name = item.Name,
                    MenuIcon = item.MenuIcon,
                    Component = item.Component,
                    IsOpen = item.IsOpen,
                    Sort = item.Sort,
                    RequireAuth = item.RequireAuth,
                    Redirect = item.Redirect,
                    CreateTime = item.CreateTime,
                    CreateUser = item.CreateUser,
                };
                list.Add(model);
            }

            //把菜单递归转换成前端能识别的树形接口
            var menuDaoList = MenuCore.GetMenuTreeList(list);
            receiveStatus.data = menuDaoList;
            receiveStatus.msg = "获取成功";
            return receiveStatus;
        }

        /// <summary>
        /// 获取菜单列表
        /// </summary>
        /// <returns></returns>
        public List<SysMenuOutPut> GetAllMenuTreeList()
        {
            var menuList = _menuRepository.GetAllMenuTreeList();
            var menuTreeList = MenuCore.GetMenuTreeList(menuList);
            return menuTreeList;
        }

        /// <summary>
        /// 获取公司下系统的菜单
        /// </summary>
        /// <param name="corporationKey">公司key</param>
        /// <param name="systemKey">系统key</param>
        /// <returns></returns>
        public ReceiveStatus<TreeOutPut> GetCorporationSystemMenuList(string corporationKey, string systemKey)
        {
            ReceiveStatus<TreeOutPut> receiveStatus = new();
            if (string.IsNullOrEmpty(corporationKey))
                return ExceptionHelper<TreeOutPut>.CustomExceptionData("公司不能为空！");
            if (string.IsNullOrEmpty(systemKey))
                return ExceptionHelper<TreeOutPut>.CustomExceptionData("系统不能为空！");

            //公司信息
            var corporationModel = _sysCorporationRepository.GetByKey(corporationKey, BaseSqlRepository.sysCorporation_selectByKeySql);
            if (corporationModel == null)
                return ExceptionHelper<TreeOutPut>.CustomExceptionData("公司不存在！");
            if (corporationModel.IsOpen == false)
                return ExceptionHelper<TreeOutPut>.CustomExceptionData("公司已停用，不能设置！");

            //系统信息
            var sysModel = _sysSystemRepository.GetByKey(systemKey, BaseSqlRepository.sysSystem_selectByKeySql);
            if (sysModel == null)
                return ExceptionHelper<TreeOutPut>.CustomExceptionData("系统不存在！");
            if (sysModel.IsOpen == false)
                return ExceptionHelper<TreeOutPut>.CustomExceptionData("系统已停用,不能设置！");

            var corporationSystemMenuList = _menuRepository.GetCorporationSystemMenuList(corporationKey, systemKey);
            foreach (var item in corporationSystemMenuList)
            {
                item.disabled = (Const.OverallAuth_MenuKey.Any(f => f == item.key) || item.nodeType != (int)NodeTypeEnum.Menu) ? true : false;
            }

            if (corporationSystemMenuList.Count > 0)
            {
                //把菜单递归转换成树形结构
                var tree = corporationSystemMenuList.ConvertTreeData();
                receiveStatus.data = tree;
            }
            else
                receiveStatus.data = [];
            return receiveStatus;
        }

        /// <summary>
        /// 获取公司、系统、菜单关系数据
        /// </summary>
        /// <param name="corporationKey">公司key</param>
        /// <returns></returns>
        public ReceiveStatus<TreeOutPut> GetAllMenuList(string corporationKey)
        {
            ReceiveStatus<TreeOutPut> receiveStatus = new();

            //公司信息
            var corporationModel = _sysCorporationRepository.GetByKey(corporationKey, BaseSqlRepository.sysCorporation_selectByKeySql);
            if (corporationModel == null)
                return ExceptionHelper<TreeOutPut>.CustomExceptionData("公司不存在！");
            if (corporationModel.IsOpen == false)
                return ExceptionHelper<TreeOutPut>.CustomExceptionData("公司已停用，不能设置！");

            //获取公司、系统、菜单
            var corporationSystemMenuList = _menuRepository.GetCorporationSystemMenuData(corporationKey, string.Empty);

            //把菜单递归转换成树形结构
            var tree = corporationSystemMenuList.ConvertTreeData();
            receiveStatus.data = tree;

            return receiveStatus;
        }
        #endregion
    }
}
